#include "ubvm_text.h"
#include "DIVA_Manager.h"
#include <sstream>
#include "xParameterPack.h"
#include "vmLibrary.h"

BOOL CALLBACK ASCIIDialog( HWND, UINT, WPARAM, LPARAM);

extern HINSTANCE _hInst ;  // this instance is defined in DIVA_MAIN
extern HWND _hWnd ;        // this instance is defined in DIVA_Application
ubvm_text *texVM ;

string ubvm_text::materials[] = {"Basic_Black","Basic_Red","Basic_Green","Basic_Blue","Basic_LightBlue","Basic_Purple","Basic_White","Basic_Yallow"};

ubvm_text::ubvm_text(xParameterPack xpp):DIVA_VM(xpp){

	int default_port_number = vmLibrary::instance().get_vm_default_input_parameters().size();
	_wop = xpp.paras[default_port_number].val_wop;
	_val = _wop->getValAddr();
	mode = 0;
	length = 0;
	height = 0;
	width = 0;
	record_asc_size = 0;
	bg_length = xpp.paras[default_port_number+1].val_int;  /// 代表 X 方向 也就是長度
	bg_height = xpp.paras[default_port_number+2].val_int; /// 代表 Y 方向 也就是高度
	bg_width = xpp.paras[default_port_number+3].val_int;  /// 代表 Z 方向 也就是浮出來的距離
	_attribute_material = materials[xpp.paras[default_port_number+4].val_int];
	_assign_material = materials[xpp.paras[default_port_number+5].val_int];
	_value_material = materials[xpp.paras[default_port_number+6].val_int];
	_background_material = materials[xpp.paras[default_port_number+7].val_int];
	_margin = xpp.paras[default_port_number+8].val_int;
	_text_scene_node = _SceneNode->createChildSceneNode();
	_text_scene_node->setInheritScale(false);  // when text panel is scaled, text is not scaled
	init_default_parameters();
	init_background_size();
	margin(_margin);
}
/// destructor
ubvm_text::~ubvm_text(){
}

void ubvm_text::load_3Dresources() {
	std::string meshName = "cube.mesh";
	/// create entity and attach to the newly allocated scene node
	_ent = VL_createEntity(meshName,"Examples/RustySteel");
	_SceneNode->attachObject(_ent);

	//this->scaleBodyToAbsSize(100, 100, 100);
}
void ubvm_text::set_default_values() {
	_vm_rx_val = 0 ;
	_vm_ry_val = 0 ;
	_vm_rz_val = 0 ;

	_vm_init_sizex = 100 ;
	_vm_init_sizey = 100 ;
	_vm_init_sizez = 100 ;

	_vm_sizex_val = 100 ;
	_vm_sizey_val = 100 ;
	_vm_sizez_val = 100 ;

	_vm_sizexscale_val = 1.0 ;
	_vm_sizeyscale_val = 1.0 ;
	_vm_sizezscale_val = 1.0 ;

	_vm_r_val = 1.0;
	_vm_g_val = 1.0;
	_vm_b_val = 1.0;
	_vm_transparency_val = 1.0 ;

	_vm_yaw_val = 0 ;
	_vm_pitch_val = 0 ;
	_vm_roll_val = 0 ;
}
void ubvm_text::reg_event_entity() {

	// register the relation of the entity and vm in diva manager
	// When this entity is clicked, mouse/keyboard VM will be passed to this VM
	// By default it can be only one entity representing this VM
	VL_regBoundingBox(_ent);

}

void ubvm_text::init_private_attrs_started() {}

void ubvm_text::init_private_attrs_ended() {}

void ubvm_text::init_background_size(){
	if(bg_length > 0 || bg_height > 0  || bg_width > 0){
		scaleBodyToAbsSize(bg_length,bg_height, bg_width);
	}
	else if(length >0 || height >0 || width >0){
		scaleBodyToAbsSize(Ogre::Vector3(length * _collect_node.size()*1.2,height * (record_asc_size + 1) * 1.5,width * 2));
	}
	else{
		//scaleBodyToAbsSize(0,0,0);
	}
}
void ubvm_text::init_print_name(){
	if(_name!=""){
		_current_material = _attribute_material;
		translate_stringToMesh(_name);
		//translate_stringToMesh("123\nn\n\n888\n\n\n");
		_current_material = _assign_material;
		translate_stringToMesh(":=");
	}
	_current_material = _value_material;
	translate_stringToMesh((*_val));
	set_position();
}

void ubvm_text::VMValueUpdated() {
	reset();
	init_print_name();
	init_background_size();
}

void ubvm_text::setBodyScale(Ogre::Vector3 scale) {
	_SceneNode ->setScale(scale);
}
bool ubvm_text::isBodyScaleWrtSceneNode() { return true ; }

Ogre::Vector3 ubvm_text::getOriginalBodySize() {
	Ogre::AxisAlignedBox temp = _ent ->getBoundingBox();	
	Ogre::Vector3 size = temp.getSize(); 
	return size ;
}

Ogre::Vector3 ubvm_text::getActualSize() {
	return getOriginalBodySize() * _SceneNode->getScale();
}
Ogre::Vector3 ubvm_text::getBodyScale() {
	return _SceneNode->getScale();
}
void ubvm_text::translate_stringToMesh(Ogre::String s ){
	for(unsigned int i=0;i<s.size();i++){

		///處裡 \n 的問題
		if(s[i] == 10){
			texVM = this;
			/*TODO:change to Qt dialog*/
			//DialogBox( _hInst, "ASCII", _hWnd, (DLGPROC)ASCIIDialog) ;

			///ASCII的位置以及他的mode
			if(mode == 1){
				Load_Mesh(32);
				ASCII_PAIR* asc = (struct ascii_pair *)malloc(sizeof(struct ascii_pair));
				asc->position = i;
				asc->mode = mode;
				asc_pos.push_back(asc);
				continue;
			}
			else if(mode == 2){
				Load_Mesh('\\');
				Load_Mesh('n');
				i++;
				continue;
			}
		}
		///處裡 \r 的問題
		if(s[i] == 13){
			texVM = this;
			/*TODO:change to Qt dialog*/
			//DialogBox( _hInst, "ASCII", _hWnd, (DLGPROC)ASCIIDialog) ;
			///ASCII的位置以及他的mode

			if(mode == 1){
				Load_Mesh(32);
				ASCII_PAIR* asc = (struct ascii_pair *)malloc(sizeof(struct ascii_pair));;
				asc->position = i;
				asc->mode = mode;
				asc_pos.push_back(asc);
				continue;
			}
			else if(mode == 2){
				Load_Mesh('\\');
				Load_Mesh('r');
				i++;
				continue;
			}
		}

		assert(s[i] > 31);
		assert(s[i] < 129);
		Load_Mesh(s[i] );
	}
}
void ubvm_text::Load_Mesh(char c){

	Ogre::Entity* ent;

	Ogre::SceneNode* node;
	node = _text_scene_node->createChildSceneNode();

	Ogre::String temp="";
	temp.append("texture_");
	temp = temp+intToString(c);
	temp.append(".mesh");

	ent = DIVA_Manager::getInstance()->getSceneManager()->createEntity(getNewUniqueName(),temp);

	node->attachObject(ent);
	node->setInheritScale(false);
	ent->setMaterialName(_current_material);
	length = max(length, ent->getBoundingBox().getSize().x);
	height = max(height, ent->getBoundingBox().getSize().y);
	width  = max(width,ent->getBoundingBox().getSize().z);
	_collect_node.push_back(node);
}
void ubvm_text::set_position(){

	Ogre::Vector3 startPos = Ogre::Vector3(0,0,0);
	///判斷存放在第幾個位置
	unsigned int i = 0; 
	///在目前這一列要位移幾個length
	float y = 0.5;
	std::vector<Ogre::SceneNode*>::iterator itp = _collect_node.begin();
	std::vector<ASCII_PAIR*>::iterator it_asc ;
	record_asc_size = asc_pos.size();

	for(itp ; itp != _collect_node.end();itp++){

		if(asc_pos.size() != 0 ){
			it_asc = asc_pos.begin();
			if(i == (*it_asc)->position){
				y = 0;
				startPos.x = 0;
				startPos.y -= height                                                                                                                                  ;
				///刪掉已經處裡完的asc_pos
				ASCII_PAIR* asc = *it_asc;
				asc_pos.erase(it_asc);
				free(asc);
				(*itp)->setVisible(false);

				//it_asc++;
			}
		}
		Ogre::Vector3 aaaa = Ogre::Vector3(startPos.x + y * length * 0.8 , startPos.y + height * record_asc_size / 2.0-height/2 , startPos.z + width);
		(*itp)->setPosition(aaaa);
		i++;
		y++;
	}

	/*	///調整用的 因為做完上面的動作可能會有超出我們的外框
	for(itp = _collect_node.begin(); itp != _collect_node.end();itp++){
	Vector3 self_pos = (*itp)->getPosition();

	(*itp)->setPosition(self_pos.x,self_pos.y + height * record_asc_size ,self_pos.z);
	}

	*/
}
void ubvm_text::reset(){
	std::vector<Ogre::SceneNode*>::iterator itp = _collect_node.begin();
	for(itp; itp != _collect_node.end();itp++){
		(*itp)->detachAllObjects();
	}
	_collect_node.clear();
	_text_scene_node->detachAllObjects();
}

void ubvm_text::margin(int _margin){
	Ogre::Vector3 text_pos = Ogre::Vector3(0,0,0);
	switch(_margin){
		case 0: ///靠左對齊
			text_pos.x = text_pos.x - this->getActualSize().x / this->getSceneNodeScale().x / 2.1;
			_text_scene_node->setPosition(text_pos);
			break;
		case 1:///靠右對齊
			text_pos.x = text_pos.x + this->getActualSize().x / this->getSceneNodeScale().x / 1.6 - _collect_node.size() * length / this->getSceneNodeScale().x;	
			_text_scene_node->setPosition(text_pos);
			break;
		case 2:///置中
			text_pos.x = text_pos.x - _collect_node.size() * length / 2.5 / this->getSceneNodeScale().x;
			_text_scene_node->setPosition(text_pos);
			break;
		default:
			assert(false);
	}
}